package com.hulk.dryad.web.control;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.ms.sequence.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.hulk.dryad.common.annotation.PrintlnLog;
import com.hulk.dryad.common.annotation.Idempotent;
import com.hulk.dryad.common.annotation.RespData;
import com.hulk.dryad.common.constant.CacheConstants;
import com.hulk.dryad.common.constant.CommonConstants;
import com.hulk.dryad.common.constant.enums.*;
import com.hulk.dryad.common.exception.BaseRteException;
import com.hulk.dryad.common.exception.WebRteException;
import com.hulk.dryad.common.util.BCryptPasswordEncoderUtil;
import com.hulk.dryad.common.util.IDWorkerRadix;
import com.hulk.dryad.common.util.SaltGenerator;
import com.hulk.dryad.manage.provider.transaction.CustomerTransaction;
import com.hulk.dryad.persistence.entity.CustomerLoginInfo;
import com.hulk.dryad.persistence.entity.CustomerOperator;
import com.hulk.dryad.persistence.service.impl.CustomerLoginInfoServiceImpl;
import com.hulk.dryad.web.api.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.time.LocalDateTime;

/**
 * @author lqx
 */
@Api(value = " customer", tags = "用户模块")
@ApiSort(3)
@Slf4j
@RestController
@RequestMapping("/customer")
@AllArgsConstructor
public class CustomerController {

    private CustomerLoginInfoServiceImpl customerLoginInfoServiceImpl;
    private CustomerTransaction customerTransaction;
    private CacheManager cacheManager;

    /**
     * <post>用户注册</post>
     *
     * @param reqDto 用户注册
     * @return R
     */
    @ApiOperation(value = "register", notes = "用户注册")
    @ApiOperationSupport(order = 0)
    @PrintlnLog
    @Idempotent
    @RespData
    @PostMapping("/register")
    public CustomerRegisterRespVO register(@RequestBody @Valid CustomerRegisterReqVO reqDto) {
        String workId = IdWorker.getId() + "";
        log.info("workId:[{}] 用户注册,入参:[{}]", workId, reqDto);
        CustomerRegisterRespVO respDto;
        try {
            CustomerLoginInfo customer = customerLoginInfoServiceImpl.getOne(Wrappers.<CustomerLoginInfo>lambdaQuery()
                    .eq(CustomerLoginInfo::getLoginNo, reqDto.getLoginNo()).eq(CustomerLoginInfo::getLoginType,LoginType.PWD.getType()));
            if (null != customer) {
                throw new BaseRteException(BEC.E_2016);
            }

            String operatorNo = IDWorkerRadix.getDTMId();
            /*密码加密盐*/
            String passSalt = SaltGenerator.generateSalt();
            String loginPassword = reqDto.getLoginPwd();//// TODO: 2020/10/13  此处应为解密请求登陆密码后的结果，加解密方式自定义

            CustomerLoginInfo loginInfo = new CustomerLoginInfo();
            loginInfo.setId(IdWorker.getId());
            loginInfo.setOperatorNo(operatorNo);
            loginInfo.setLoginNo(reqDto.getLoginNo());
            loginInfo.setLoginSignChannel(reqDto.getChannel());
            loginInfo.setLoginType(LoginType.PWD.getType());
            loginInfo.setLoginStatus(CustomerLoginStatus.NORMAL.getType());
            loginInfo.setCreatedTime(LocalDateTime.now());
            loginInfo.setCreatedBy(CommonConstants.DEFUAULT_CREATER);

            CustomerOperator operatorInfo = new CustomerOperator();
            operatorInfo.setId(IdWorker.getId());
            operatorInfo.setOperatorNo(operatorNo);
            operatorInfo.setOperatorName(reqDto.getName());
            operatorInfo.setOperatorLvl(OperatorLevel.NOVICE.getType());
            operatorInfo.setNickName(reqDto.getNickName());
            operatorInfo.setLoginPwd(BCryptPasswordEncoderUtil.encode(loginPassword).replace("{bcrypt}", ""));
            operatorInfo.setLoginSalt(passSalt);
            operatorInfo.setRealnameStatus(YNFlag.N.getCode());
            operatorInfo.setLoginRightRange(OperatorLoginRange.ALL.getType());
            operatorInfo.setIdentity(null);
            operatorInfo.setOperatorStatus(OperatorStatus.NORMAL.getType());
            operatorInfo.setDataSourceType(OperatorSource.NORMAL.getType());
            operatorInfo.setPwdCreateType(PwdCreateType.CUSTOMER.getType());
            operatorInfo.setCreatedBy(CommonConstants.DEFUAULT_CREATER);
            operatorInfo.setCreatedTime(LocalDateTime.now());
            operatorInfo.setRsv1(RandomStringUtils.randomAlphabetic(32));
            customerTransaction.insertCustomerRelates(workId, loginInfo, operatorInfo);

            respDto = new CustomerRegisterRespVO();
            respDto.setLoginNo(reqDto.getLoginNo());
            respDto.setEncryptKey(operatorInfo.getRsv1());
            respDto.setFinishTime(LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN));
        } catch (BaseRteException ex) {
            log.error("workId:[{}] 用户注册,异常:[{}]", workId, ex);
            throw ex;
        } catch (Exception e) {
            log.error("workId:[{}] 用户注册,异常:[{}]", workId, e);
            throw new WebRteException(BEC.E_9999);
        }
        log.info("workId:[{}] 用户注册,返回:[{}]", workId, respDto);
        return respDto;
    }




    /**
     * logout
     *
     * @param reqVo reqVo
     * @return R
     */
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "logout", notes = "用户登出")
    @PrintlnLog
    @RespData
    @PostMapping("/logout")
    public void logout(@RequestBody @Valid CustomerLogoutReqVO reqVo) {
        String workId = IdWorker.getId() + "";
        log.info("workId:[{}] 用户登出,入参:[{}]", workId, reqVo);
        try {
            CustomerLoginInfo customer = customerLoginInfoServiceImpl.getOne(Wrappers.<CustomerLoginInfo>lambdaQuery()
                    .eq(CustomerLoginInfo::getLoginNo, reqVo.getLoginNo()).eq(CustomerLoginInfo::getLoginType,reqVo.getLoginType()));
            if (null == customer) {
                throw new WebRteException(BEC.E_2015);
            }
            //清除登陆记录
            clearLoginNoCache(reqVo.getLoginNo());
        } catch (BaseRteException ex) {
            log.error("workId:[{}] 用户登出,异常:[{}]", workId, ex);
            throw ex;
        } catch (Exception e) {
            log.error("workId:[{}] 用户登出,异常:[{}]", workId, e);
            throw new WebRteException(BEC.E_9999);
        }
        log.info("workId:[{}] 用户登出处理完成!", workId);
    }

    /**
     * 清除登录缓存
     *
     * @param loginNo 登录号
     */
    private void clearLoginNoCache(String loginNo) {
        Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
        if (null != cache) {
            if (null != cache.get(loginNo)) {
                cache.evict(loginNo);
            }
        }
    }
}